﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using ZXing;
using ZXing.Common;
using ZXing.QrCode;

namespace glb
{
    public class LabelXmlPrintHelper
    {
        /// <summary>
        /// 要打印的条码或二维码值
        /// </summary>
        public string barcode { set; get; }
        /// <summary>
        /// 标签预览图
        /// </summary>
        public Bitmap LabelBmp { get { return this.qrBmp; } }

        private string lableConfigFile;
        private Bitmap qrBmp;
        XmlDocument xmlDocument = new XmlDocument();

        XmlNodeList nodeList;

        public LabelXmlPrintHelper(string xmlConfigFile)
        {
            this.lableConfigFile = xmlConfigFile;

            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true;
            XmlReader reader = XmlReader.Create(lableConfigFile, settings);
            xmlDocument.Load(reader);

            nodeList = xmlDocument.GetElementsByTagName("字段");
            if (reader != null)
            {
                reader.Close();
            }
        }

        public void CreateLabelByXml(PrintPageEventArgs e, Dictionary<string, string> myDict)
        {
            this.CreateLabelByXml(e.Graphics, myDict);
        }

        public void ReReadxml()
        {
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true;
            XmlReader reader = XmlReader.Create(lableConfigFile, settings);
            xmlDocument.Load(reader);

            nodeList = xmlDocument.GetElementsByTagName("字段");
            if (reader != null)
            {
                reader.Close();
            }
        }

        /// <summary>
        /// 使用方法，放到Printer_PrintPageBag里调用
        /// xmlPrint.barcode="XXXXXXXX";
        /// Dictionary<string, string> myDict = new Dictionary<string, string>();
        /// myDict.Add("品名", this.袋标品名.Text);
        /// xmlPrint.CreateLabelByXml(e.Graphics, myDict);
        /// </summary>
        /// <param name="g"></param>
        /// <param name="myDict">字段内容字典</param>
        public void CreateLabelByXml(Graphics g, Dictionary<string, string> myDict)
        {
            try
            {
                foreach (XmlNode item in nodeList[0].ChildNodes)
                {
                    if (item.Attributes["name"].Value == "QRCODE")
                    {
                        #region 二维码
                        this.DrawQRCode(g,
                            item.Attributes["width"].Value,
                            item.Attributes["height"].Value,
                            item.Attributes["x"].Value,
                            item.Attributes["y"].Value
                            );
                        #endregion
                    }
                    else if (item.Attributes["name"].Value == "BARCODE")
                    {
                        #region 条码
                        this.DrawBarcode(g,
                            item.Attributes["width"].Value,
                            item.Attributes["height"].Value,
                            item.Attributes["pureBracode"].Value,
                            item.Attributes["x"].Value,
                            item.Attributes["y"].Value
                            );
                        #endregion
                    }
                    else if (item.Attributes["name"].Value == "LINE")
                    {
                        #region 线
                        this.DrawLine(g,
                             item.Attributes["penWidth"].Value,
                             item.Attributes["x1"].Value,
                             item.Attributes["y1"].Value,
                             item.Attributes["x2"].Value,
                             item.Attributes["y2"].Value
                             );
                        #endregion
                    }
                    else if (item.Attributes["name"].Value == "LINERECT")
                    {
                        #region 矩形
                        this.DrawRect(g,
                             item.Attributes["penWidth"].Value,
                             item.Attributes["x"].Value,
                             item.Attributes["y"].Value,
                             item.Attributes["width"].Value,
                             item.Attributes["height"].Value
                             );
                        #endregion
                    }
                    else if (item.Attributes["name"].Value == "IMAGE")
                    {
                        #region 图片
                        this.DrawImage(g,
                             item.Attributes["value"].Value,
                             item.Attributes["x"].Value,
                             item.Attributes["y"].Value,
                             item.Attributes["width"].Value,
                             item.Attributes["height"].Value
                             );
                        #endregion
                    }
                    else
                    {
                        #region 字段
                        string value = item.Attributes["value"].Value;
                        if (!String.IsNullOrEmpty(item.Attributes["field"].Value)) //字典变量
                        {
                            if (myDict.ContainsKey(item.Attributes["field"].Value))
                                value = myDict[item.Attributes["field"].Value];
                        }
                        if (item.Attributes["x"].Value == "-1") //自动居中
                        {
                            this.DrawStringCenter(g,
                                item.Attributes["font"].Value,
                                item.Attributes["fontStype"].Value,
                                item.Attributes["size"].Value,
                                value,
                                item.Attributes["x1"].Value,
                                item.Attributes["y"].Value,
                                item.Attributes["width"].Value,
                                item.Attributes["height"].Value
                                 );
                        }
                        else
                        {
                            this.DrawString(g,
                               item.Attributes["font"].Value,
                               item.Attributes["fontStype"].Value,
                               item.Attributes["size"].Value,
                               value,
                               item.Attributes["x"].Value,
                               item.Attributes["y"].Value
                                );
                        }
                        #endregion
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("CreateLabelByXml " + ex.Message + ex.StackTrace, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #region Draw Method
        private void DrawString(Graphics g, string fontName, string fontStype, string size, string value, string x, string y)
        {
            FontStyle style = (FontStyle)Enum.Parse(typeof(FontStyle), fontStype);

            Font font = new Font(fontName, Convert.ToSingle(size), style);
            g.DrawString(value, font, Brushes.Black, Convert.ToSingle(x), Convert.ToSingle(y));
        }
        private void DrawStringCenter(Graphics g, string fontName, string fontStype, string size, string value, string x, string y, string width, string height)
        {
            FontStyle style = (FontStyle)Enum.Parse(typeof(FontStyle), fontStype);
            Font font = new Font(fontName, Convert.ToSingle(size), style);

            StringFormat stringFormat = new StringFormat();
            stringFormat.LineAlignment = StringAlignment.Center;
            stringFormat.Alignment = StringAlignment.Center;

            RectangleF lbRect = new RectangleF(
                Convert.ToSingle(x),
                Convert.ToSingle(y),
                Convert.ToSingle(width),
                Convert.ToSingle(height));
            g.DrawString(value, font, Brushes.Black, lbRect, stringFormat);
        }
        private void DrawRect(Graphics g, string penWidth, string x, string y, string width, string height)
        {
            float fwidth = 1.0f;
            float.TryParse(penWidth, out fwidth);
            Pen pen = new Pen(Brushes.Black, fwidth);

            g.DrawRectangle(pen, Convert.ToInt16(x), Convert.ToInt16(y), Convert.ToInt16(width), Convert.ToInt16(height));
        }
        private void DrawLine(Graphics g, string penWidth, string x1, string y1, string x2, string y2)
        {
            float fwidth = 1.0f;
            float.TryParse(penWidth, out fwidth);
            Pen pen = new Pen(Brushes.Black, fwidth);

            g.DrawLine(pen, Convert.ToInt16(x1), Convert.ToInt16(y1), Convert.ToInt16(x2), Convert.ToInt16(y2));
        }
        private void DrawBarcode(Graphics g, string width, string height, string pureBracode, string x, string y)
        {
            int iwidth = 240;
            int iheight = 40;
            int ix = 4;
            int iy = 110;
            int.TryParse(width, out iwidth);
            int.TryParse(height, out iheight);
            int.TryParse(x, out ix);
            int.TryParse(y, out iy);

            if (pureBracode == "1")
            {
                g.DrawImageUnscaled(BarCode(barcode, iwidth, iheight, true), ix, iy);
            }
            else
            {
                g.DrawImageUnscaled(BarCode(barcode, iwidth, iheight, false), ix, iy);
            }
        }
        private void DrawQRCode(Graphics g, string width, string height, string x, string y)
        {
            int iwidth = 550;
            int iheight = 550;
            int ix = 4;
            int iy = 110;
            int.TryParse(width, out iwidth);
            int.TryParse(height, out iheight);
            int.TryParse(x, out ix);
            int.TryParse(y, out iy);

            this.qrBmp = GenerateQRCode(barcode, iwidth, iheight);
            g.DrawImage(this.qrBmp, ix, iy, iwidth, iheight);//DrawImageUnscaled
        }
        private void DrawImage(Graphics g, string value, string x, string y, string width, string height)
        {
            int iwidth = 28;
            int iheight = 28;
            int ix = 6;
            int iy = 7;
            int.TryParse(width, out iwidth);
            int.TryParse(height, out iheight);
            int.TryParse(x, out ix);
            int.TryParse(y, out iy);

            if (!String.IsNullOrEmpty(value))
            {
                string path = AppDomain.CurrentDomain.BaseDirectory;
                if (File.Exists(path + value))
                {
                    Image img = Image.FromFile(path + value);
                    g.DrawImage(img, ix, iy, iwidth, iheight);
                }
            }
        }
        #endregion

        /// <summary>
        /// 生成二维码,保存成图片
        /// </summary>
        public static Bitmap GenerateQRCode(string text, int width = 500, int height = 500)
        {
            BarcodeWriter writer = new BarcodeWriter();
            writer.Format = BarcodeFormat.QR_CODE;
            QrCodeEncodingOptions options = new QrCodeEncodingOptions();
            options.DisableECI = true;
            //设置内容编码
            options.CharacterSet = "UTF-8";
            //设置二维码的宽度和高度
            options.Width = width;
            options.Height = height;
            //设置二维码的边距,单位不是固定像素
            options.Margin = 1;
            writer.Options = options;

            Bitmap map = writer.Write(text);
            return map;
        }

        /// <summary>
        /// 生成一维条码
        /// </summary>
        /// <param name="Contents"></param>
        /// <returdns></returns>
        private Bitmap BarCode(string Contents, int width = 250, int height = 50, bool pureBracode = false)
        {
            EncodingOptions options = new EncodingOptions();
            options.Width = width; //276-246
            options.Height = height;
            options.PureBarcode = pureBracode; //true
            BarcodeWriter writer = new BarcodeWriter();
            writer.Format = BarcodeFormat.CODE_128;
            writer.Options = options;
            return writer.Write(Contents);
        }
    }
}
